package com.cskaoyan.typehandler;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.MappedJdbcTypes;
import org.apache.ibatis.type.MappedTypes;
import org.apache.ibatis.type.TypeHandler;

import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
 * 该类用于将  数据库里 :形如"[1,2,3,4]"的字符串,   处理为 java 类型 Integer[] 或 List<Integer>;
 *
 * 也可以使用一个工具类自行处理(传统自己繁琐的方式),  但是使用该框架更快,更通用;
 *
 * 问题: 如何  在不影响自定义工具类的使用情况下, 添加该框架的使用;  !!不得影响!!;
 *
 * @author: 陈慧颖
 * @time: Created by chy on 2022/6/5 15:05
 */
@MappedTypes(Integer[].class)  //  java 里面的类型
@MappedJdbcTypes(JdbcType.VARCHAR)  // 告诉mybatis 在什么类型是用到 typehandler; jdbc 里面的类型
public class IntegerArrayTypeHandler implements TypeHandler<Integer[]> {
    ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 形如:   insert into market_topic  (id,username, password, topics_id) vlaues (? ? ? ?)
     * topics_id 从前端传来是一个[1,2,4] , 在 java 里是一个 Integer[] 或 list 容器, 在 sql 里是 形如"[1,2,4]"的字符串, varchar 类型;
     *
     * @param preparedStatement
     * @param i
     * @param integers
     * @param jdbcType
     * @throws SQLException
     */
    @Override
    public void setParameter(PreparedStatement preparedStatement, int i, Integer[] integers, JdbcType jdbcType) throws SQLException {
        String value = null;  // 将输入的那个[]  映射为一个 String;
        try {
            value = objectMapper.writeValueAsString(integers);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        preparedStatement.setString(i, value);
    }

    /**
     * 输出结果映射; 即从 sql 里面读取到了一个形如"[1,23]"的 varchar, 映射到一个[1,23];
     * @param resultSet
     * @param s
     * @return
     * @throws SQLException
     */
    /**
     * // new Integer[0]; 意思是: 创建一个长度为 0 的Integer 数组;
     * return new Integer[0];
     *
     * @param resultSet
     * @param s
     * @return
     * @throws SQLException
     */
    @Override
    public Integer[] getResult(ResultSet resultSet, String s) throws SQLException {
        String result = resultSet.getString(s);
        return transfer(result);
    }

    @Override
    public Integer[] getResult(ResultSet resultSet, int i) throws SQLException {
        String result = resultSet.getString(i);
        return transfer(result);
    }

    /**
     * 将从 sql 读取到的参数转化为一个数组或 list 容器;
     * @param callableStatement
     * @param i
     * @return
     * @throws SQLException
     */
    @Override
    public Integer[] getResult(CallableStatement callableStatement, int i) throws SQLException {
        String result = callableStatement.getString(i);
        return transfer(result);
    }

    private Integer[] transfer(String result){
        Integer[] integers = new Integer[0]; // new Integer[]{};

        try {
            integers = objectMapper.readValue(result, Integer[].class);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return integers;
    }
}
